package com.enation.app.javashop.consumer.shop.orderbill;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.dag.eagleshop.core.account.model.dto.payment.RefundRecordDTO;
import com.dag.eagleshop.core.account.model.enums.TradeSubjectEnum;
import com.dag.eagleshop.core.account.service.AccountManager;
import com.dag.eagleshop.core.account.utils.HttpUtils;
import com.dag.eagleshop.core.delivery.model.dto.JsonBean;
import com.enation.app.javashop.consumer.core.event.OrderStatusChangeEvent;
import com.enation.app.javashop.consumer.core.event.RefundStatusChangeEvent;
import com.enation.app.javashop.core.aftersale.model.dos.RefundDO;
import com.enation.app.javashop.core.aftersale.model.enums.AccountTypeEnum;
import com.enation.app.javashop.core.aftersale.model.enums.RefundStatusEnum;
import com.enation.app.javashop.core.aftersale.model.enums.RefuseTypeEnum;
import com.enation.app.javashop.core.base.message.OrderStatusChangeMsg;
import com.enation.app.javashop.core.base.message.RefundChangeMsg;
import com.enation.app.javashop.core.base.model.vo.SmsSendVO;
import com.enation.app.javashop.core.base.rabbitmq.AmqpExchange;
import com.enation.app.javashop.core.base.rabbitmq.TimeExecute;
import com.enation.app.javashop.core.base.service.SmsManager;
import com.enation.app.javashop.core.client.trade.BillClient;
import com.enation.app.javashop.core.member.model.dos.Member;
import com.enation.app.javashop.core.member.service.MemberManager;
import com.enation.app.javashop.core.orderbill.model.dos.BillItem;
import com.enation.app.javashop.core.orderbill.model.dto.OrderSettleMsgDTO;
import com.enation.app.javashop.core.orderbill.model.enums.BillType;
import com.enation.app.javashop.core.orderbill.utils.SettleUtils;
import com.enation.app.javashop.core.payment.model.enums.PaymentPluginEnum;
import com.enation.app.javashop.core.payment.service.RefundItemManager;
import com.enation.app.javashop.core.system.sendMessage.WechatSendMessage;
import com.enation.app.javashop.core.trade.order.model.dos.OrderDO;
import com.enation.app.javashop.core.trade.order.model.enums.OrderStatusEnum;
import com.enation.app.javashop.core.trade.order.model.enums.OrderTypeEnum;
import com.enation.app.javashop.core.trade.order.service.OrderQueryManager;
import com.enation.app.javashop.core.trade.sdk.model.OrderDetailDTO;
import com.enation.app.javashop.core.trade.sdk.model.OrderSkuDTO;
import com.enation.app.javashop.framework.trigger.Interface.TimeTrigger;
import com.enation.app.javashop.framework.util.CurrencyUtil;
import com.enation.app.javashop.framework.util.EnvironmentUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author fk
 * @version v2.0
 * @Description: 结算单消费者
 * @date 2018/4/26 15:00
 * @since v7.0.0
 */
@Service
public class OrderBillConsumer implements OrderStatusChangeEvent, RefundStatusChangeEvent {

    protected final Log logger = LogFactory.getLog(getClass());

    @Autowired
    private BillClient billClient;
    @Autowired
    private OrderQueryManager orderQueryManager;
    @Autowired
    private TimeTrigger timeTrigger;
    @Autowired
    private AccountManager accountManager;
    @Autowired
    private MemberManager memberManager;
    @Autowired
    private RefundItemManager refundItemManager;
    @Autowired
    private SmsManager smsManager;

    @Value("${service.webSocket.url}")
    private String url;

    /** 使用webSocket推消息 */
    private static final String WEB_SOCKET = "/websocket/websocket_push_message";

    // 延迟发送队列前缀名
    private static final String TRIGGER_PREFIX = "ORDER_SETTLE_ACCOUNT_";

    /**
     * 订单状态变更生成结算单和收益明细
     */
    @Override
    public void orderChange(OrderStatusChangeMsg orderMessage) {
        OrderDO orderDO = orderMessage.getOrderDO();
        String orderType = orderDO.getOrderType();
        // 付款后生成结算单项
        if(orderMessage.getNewStatus().equals(OrderStatusEnum.PAID_OFF)){
            // 代码逻辑转移到 OrderCountRefundPriceConsumer了

            //普通订单下单成功 发消息
            if(orderType.equals(OrderTypeEnum.normal.name())){
                this.sendPayMessage();
            }

        }else if(orderMessage.getNewStatus().equals(OrderStatusEnum.NEW)){
            Integer memberId = orderDO.getMemberId();
            Member member = memberManager.getModel(memberId);
            Map<String,Object> map = new HashMap<>();
            if(member != null){
                map.put("type",1);
                map.put("img",member.getFace());
                map.put("nick_name",member.getNickname());
                JSONArray array = JSON.parseArray(orderDO.getItemsJson());
                map.put("goods_num",array.size());
                map.put("discount_price",orderDO.getDiscountPrice());
            }
            // 新订单推送气泡
            WechatSendMessage.WX_MESSAGE_EXECUTOR.execute(() -> {
                String requestPath = url + WEB_SOCKET;
                HttpUtils.httpPostByJson(requestPath, JSON.toJSON(map).toString(), JsonBean.class);
            });
        }else if(orderMessage.getNewStatus().equals(OrderStatusEnum.ROG)){
            // 如果没有上线就先关闭下面功能 解决虚拟账户和原结算数据一致性问题
            if(!SettleUtils.isGoOnline(orderDO.getCreateTime())){
                logger.info("钱包结算功能暂未开启");
                return;
            }

            // 计算执行延迟时间
            int settleDelayMinutes = this.countDelayTime(orderDO.getOrderType());

            // 结算消息
            OrderSettleMsgDTO orderSettleMsgDTO = new OrderSettleMsgDTO();
            orderSettleMsgDTO.setOrderId(orderDO.getOrderId());
            orderSettleMsgDTO.setSettleType(1);

            // 延迟发送 定时结算
            String orderSn = orderDO.getSn();
            Long startTime = orderDO.getSigningTime();
            // 计算执行时间
            long orderSettleExeTime = this.getOrderSettleExeTime(startTime, settleDelayMinutes);
            timeTrigger.add(TimeExecute.ORDER_SETTLE_EXECUTER, orderSettleMsgDTO , orderSettleExeTime, TRIGGER_PREFIX + orderSn);
        }
    }

    /**
     * 退款生成一条结算单
     */
    @Override
    public void refund(RefundChangeMsg refundChangeMsg) {
        logger.info("退款消息:" + JSON.toJSON(refundChangeMsg).toString());
        RefundDO refund = refundChangeMsg.getRefund();
        String refuseType = refund.getRefuseType();
        RefundStatusEnum refundStatusEnum = refundChangeMsg.getRefundStatusEnum();

        OrderDetailDTO orderDetailDTO = orderQueryManager.getModel(refund.getOrderSn());
        OrderDO orderDO = orderQueryManager.getModel(orderDetailDTO.getOrderId());

        //审核通过的和取消订单的退款单需要生成结算单
        if (refundStatusEnum.equals(RefundStatusEnum.PASS)) {
            BillItem billItem = billClient.buildBillItem(refund.getOrderSn(), BillType.REFUND);
            billItem.setRefundSn(refund.getSn());
            billItem.setRefundTime(refund.getCreateTime());
            billItem.setPrice(refund.getRefundPrice());
            this.billClient.add(billItem);
        }

        // 如果没有上线就先关闭下面功能 解决虚拟账户和原结算数据一致性问题
        if(!SettleUtils.isGoOnline(orderDO.getCreateTime())){
            logger.info("钱包结算功能暂未开启");
            return;
        }

        // 如果审核通过或者退款中(补救) 就停止定时器
        if((refundStatusEnum.equals(RefundStatusEnum.PASS)
                || refundStatusEnum.equals(RefundStatusEnum.REFUNDING))
                && RefuseTypeEnum.RETURN_MONEY.value().equals(refuseType)){
            logger.info("停止订单结算定时器：" + refund.getOrderSn());
            // 如果已经确认收货 并且还没有结算 需要将结算定时器关闭
            Long startTime = orderDO.getSigningTime();
            if(startTime != null){
                // 计算执行延迟时间
                int settleDelayMinutes = this.countDelayTime(orderDO.getOrderType());
                // 计算执行时间
                long orderSettleExeTime = this.getOrderSettleExeTime(startTime, settleDelayMinutes);
                // 删除计算
                timeTrigger.delete(TimeExecute.ORDER_SETTLE_EXECUTER, orderSettleExeTime, TRIGGER_PREFIX + orderDO.getSn());
                logger.info("删除成功：" + refund.getOrderSn());
            }
        }

        // 订单实际退款生成退款记录
        if(refundStatusEnum.equals(RefundStatusEnum.REFUNDING)
                && RefuseTypeEnum.RETURN_MONEY.value().equals(refuseType)){
            if (refund.getAccountType().equals(AccountTypeEnum.WALLETPAY.value())) {
                logger.debug("订单【" + refund.getOrderSn() + "】：为钱包支付，已生成过退款记录");
                return;
            }
            logger.info("订单实际退款：" + refund.getOrderSn());

            // 查询会员
            Integer memberId = refund.getMemberId();
            Member member = memberManager.getModel(memberId);
            String accountMemberId = member.getAccountMemberId();

            RefundRecordDTO refundRecordDTO = new RefundRecordDTO();
            refundRecordDTO.setTradeVoucherNo(refund.getOrderSn());
            Double refundPrice = refund.getRefundPrice();
            if (refund.getAccountType().equals(AccountTypeEnum.MERGEPAY.value())) {
                double walletRefundPrice = refundItemManager.querySuccessRefundPriceByRefundSn(refund.getSn(), PaymentPluginEnum.walletPayPlugin.name());
                refundPrice = CurrencyUtil.sub(refundPrice, walletRefundPrice);
            }
            refundRecordDTO.setAmount(BigDecimal.valueOf(refundPrice));
            refundRecordDTO.setTradeSubject(TradeSubjectEnum.ORDER_REFUND_WEIXIN.description());
            refundRecordDTO.setTradeContent("订单号" + orderDO.getSn() + "交易款项");
            refundRecordDTO.setTradeTime(new Date(refund.getRefundTime() * 1000));
            refundRecordDTO.setOperatorId(accountMemberId);
            refundRecordDTO.setOperatorName(member.getNickname());
            accountManager.refundRecord(refundRecordDTO);
            logger.info("订单实际退款成功：" + refund.getOrderSn());
        }
    }



    /**
     * 计算订单结算延迟时间
     */
    private int countDelayTime(String orderType){
        // 立即结算 之前这里有场景判断  现在改为立即结算
        return 0;
    }


    /**
     * 订单结算执行时间
     */
    private long getOrderSettleExeTime(long startTime, int minutes){
        Date exeTime = DateUtils.addMinutes(new Date(startTime * 1000), minutes);
        return exeTime.getTime() / 1000;
    }

    /**
     * 商城普通订单支付完成发短息 给管理员
     */
    private void sendPayMessage(){
        // 生产环境发短息
        if(EnvironmentUtils.isProd()){
            SmsSendVO smsSendVO = new SmsSendVO();
            smsSendVO.setContent("收到一个智溢商城商城订单，请及时处理并发货。");
            smsSendVO.setMobile("15960179760");//罗秋菊手机号
            //发送短信验证码
            smsManager.send(smsSendVO);
        }
    }

}
